{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0e11f304",
   "metadata": {},
   "source": [
    "#  7\\.  使用矩阵计算岭回归系数  # \n",
    "\n",
    "##  7.1.  介绍  # \n",
    "\n",
    "前面的实验中，我们学习了岭回归和 LASSO 回归方法，并使用 scikit-learn 对两种方法进行了实战训练。本次挑战中，我们将尝试直接使用 Python 完成岭回归系数  $w$  计算，并与 scikit-learn 计算结果进行比较。 \n",
    "\n",
    "##  7.2.  知识点  # \n",
    "\n",
    "  * 使用 Python 计算岭回归系数 \n",
    "\n",
    "  * 使用 scikit-learn 计算岭回归系数 \n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba00839f",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "##  7.3.  使用 Python 计算岭回归系数  # \n",
    "\n",
    "前面的课程中，我们已经知道了岭回归的向量表达式： \n",
    "\n",
    "$$ F_{R i d g e}=\\|y-X w\\|_{2}^{2}+\\lambda\\|w\\|_{2}^{2} \\tag{1} $$ \n",
    "\n",
    "以及该向量表达式的解析解： \n",
    "\n",
    "$$\\hat w_{Ridge} = (X^TX + \\lambda I)^{-1} X^TY \\tag{2}$$ \n",
    "\n",
    "Exercise 7.1 \n",
    "\n",
    "挑战：参考公式  $(2)$  ，完成 Python 实现岭回归系数  $w$  的计算函数。 \n",
    "\n",
    "提示：使用 ` np.eye()  ` 生成单位矩阵，并注意公式是矩阵乘法。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "fe4d6f65",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def ridge_regression(X, Y, alpha):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    X -- 自变量数据矩阵\n",
    "    Y -- 因变量数据矩阵\n",
    "    alpha -- lamda 参数\n",
    "\n",
    "    返回:\n",
    "    W -- 岭回归系数\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (≈ 3 行代码)\n",
    "\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return W"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18c43162",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 7.1 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "d36e219b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def ridge_regression(X, Y, alpha):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    X -- 自变量数据矩阵\n",
    "    Y -- 因变量数据矩阵\n",
    "    alpha -- lamda 参数\n",
    "\n",
    "    返回:\n",
    "    W -- 岭回归系数\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (≈ 3 行代码)\n",
    "    XTX = X.T * X\n",
    "    reg = XTX + alpha * np.eye(np.shape(X)[1])\n",
    "    W = reg.I * (X.T * Y) \n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return W"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "361d71fa",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "下面，我们生成测试数据： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "613a91f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "np.random.seed(10) # 设置随机数种子\n",
    "\n",
    "X = np.matrix(np.random.randint(5, size=(10, 10)))\n",
    "Y = np.matrix(np.random.randint(10, size=(10,1 )))\n",
    "alpha = 0.5"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8e01c87",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "运行测试 \n",
    "\n",
    "计算岭回归系数  $w$  的值： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "206f53e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 1.42278923,  2.20583559, -0.6391644 ,  0.64022529, -0.44014758,\n",
       "          1.66307858, -0.83879894, -0.25611354, -0.06951638, -2.56882017]])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ridge_regression(X, Y, alpha).T"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2aa4fe0",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "##  7.4.  使用 scikit-learn 计算岭回归系数  # \n",
    "\n",
    "上面的挑战中，你已经学会了使用 Python 计算岭回归系数  $w$  。下面，我们看一看结果是否与 scikit-learn 的计算结果一致。 \n",
    "\n",
    "Exercise 7.2 \n",
    "\n",
    "挑战：使用 scikit-learn 计算岭回归系数  $w$  。 \n",
    "\n",
    "提示：请向岭回归模型中增加 ` fit_intercept=False  ` 参数取消截距。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "dd80ffae",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.linear_model import Ridge\n",
    "\n",
    "def ridge_model(X, Y, alpha):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    X -- 自变量数据矩阵\n",
    "    Y -- 因变量数据矩阵\n",
    "    alpha -- lamda 参数\n",
    "\n",
    "    返回:\n",
    "    W -- 岭回归系数\n",
    "    \"\"\"\n",
    "\n",
    "    ### 代码开始 ### (≈ 3 行代码)\n",
    "\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return W"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95fc2ee6",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 7.2 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "0defb8ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.linear_model import Ridge\n",
    "\n",
    "def ridge_model(X, Y, alpha):\n",
    "    \"\"\"\n",
    "    参数:\n",
    "    X -- 自变量数据矩阵\n",
    "    Y -- 因变量数据矩阵\n",
    "    alpha -- lamda 参数\n",
    "\n",
    "    返回:\n",
    "    W -- 岭回归系数\n",
    "    \"\"\"\n",
    "    # 确保 X 和 Y 是 numpy 数组\n",
    "    X = np.asarray(X)\n",
    "    Y = np.asarray(Y)\n",
    "\n",
    "    ### 代码开始 ### (≈ 3 行代码)\n",
    "    model = Ridge(alpha, fit_intercept=False)\n",
    "    model.fit(X,Y)\n",
    "    W = model.coef_\n",
    "    ### 代码结束 ###\n",
    "\n",
    "    return W"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07d666fa",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "运行测试 \n",
    "\n",
    "计算岭回归系数  $w$  的值： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8452f31e",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'Markdown' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNameError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[39]\u001b[39m\u001b[32m, line 8\u001b[39m\n\u001b[32m      5\u001b[39m alpha = \u001b[32m0.5\u001b[39m\n\u001b[32m      7\u001b[39m \u001b[38;5;66;03m# 先输出文本\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m8\u001b[39m display(\u001b[43mMarkdown\u001b[49m(\u001b[33m\"\u001b[39m\u001b[33m**注意**：以下为实验数据，请谨慎参考。\u001b[39m\u001b[33m\"\u001b[39m))\n\u001b[32m      9\u001b[39m ridge_model(X, Y, alpha)\n",
      "\u001b[31mNameError\u001b[39m: name 'Markdown' is not defined"
     ]
    }
   ],
   "source": [
    "np.random.seed(10) # 设置随机数种子\n",
    "\n",
    "X = np.array(np.random.randint(5, size=(10, 10)))\n",
    "Y = np.array(np.random.randint(10, size=(10,1 )))\n",
    "alpha = 0.5\n",
    "\n",
    "ridge_model(X, Y, alpha)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1015ee80",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "期望输出 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2cebb8a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "matrix([[ 1.42278923,  2.20583559, -0.6391644 ,  0.64022529, -0.44014758,\n",
    "          1.66307858, -0.83879894, -0.25611354, -0.06951638, -2.56882017]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a88a92ad",
   "metadata": {},
   "source": [
    "我们可以看到，和预想的一致，两种方法计算出的  $w$  系数值是一模一样的。 \n",
    "\n",
    "* * *\n"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
